import { ref, onActivated, onDeactivated, reactive } from "vue";
import NERTC from "nertc-web-sdk/NERTC";
import ajax from "@/util/request";
import config from "@/config";
import store from "@/store";

/**
 * 初始化
 * @param subscribeLocalVideo: 是否订阅本地视频（如果需要传入一个要展示视频的Dom节点）
 * @param subscribeRemoteVideo: 是否订阅远程视频 
 * @returns 
 */
const setup = () => {

    const joinChannel = ref(false);
    const token = ref("");
    const logs = reactive<string[]>([]);

    interface IUserListData {
        t_admin_pk: number,
        remoteStream?: any,
        disableAudio?: boolean,
    }

    // 加入房间的远端用户id
    const userListData = reactive<IUserListData[]>([]);

    // 是否发送本地声音（通过开关麦克风实现）
    const localAudio = ref(true);

    // 是否发送本地视频（通过开关麦克风实现）
    const localVideo = ref(true);

    // 是否接收远端声音（通过开关远端声音流实现）
    // const recordDeviceMute = ref(true);

    const client = NERTC.createClient({
        // App Key
        appkey: config.appkey,
        // 是否开启调试日志
        debug: true,
    });

    let localStream: any = undefined;

    const setJoinChannel = async (bol: boolean,channelName = "uniapp") => {
        // 加入房间
        if (bol) {
            console.log("准备加入房间");
            const res = await ajax({
                url: "/resource/getRTCToken",
                data: {
                    uid: store.state.admin.t_admin_pk,
                },
            });

            if (res.data.code < 0) {
                console.log("获取加入房间的token失败")
                alert("获取加入房间的token失败");
                return;
            }
            token.value = res.data.data.token;

            // 重新设置麦克风的打开状态
            localAudio.value = true;
            localVideo.value = true;
            
            try {
                client
                    .join({
                        // 房间名称要填写正确
                        channelName,
                        uid: 1,
                        token: token.value, //调试模式下可设置为 null。正式上线前设置为相应的 Token，具体请参见“Token 鉴权”章节。
                        // 这里只能使用异步回调，因为promise没有reslove任何参数
                    })
                    .then(() => {
                        alert({ type: "success", message: `加入房间${channelName}成功` });
                        joinChannel.value = true;
                        // 初始化本地视频
                        addEventListener();
                        logs.unshift(`加入房间：${channelName}`);
                    });
            } catch (e) {
                console.log("加入房间失败，很有可能你已经在该房间：", e);
            }
        } else {
            // 这里只能使用异步回调，因为promise没有reslove任何参数
            client.leave().then(() => {
                alert({ type: "success", message: "离开房间成功" });
                console.log("离开房间成功");
                logs.unshift(`离开房间`);
                joinChannel.value = false;

            });
        }
    };

    /**
     * 初始化本地流
     */
    const initLocalStream = async (subscribeLocalVideo?: HTMLElement) => {
        const cameras = await NERTC.getCameras();    //获取可用的视频输入设备
        const cameraId = cameras?.cameraId;
        // if (!cameraId) {
        //     logs.push("没有可以使用的摄像头");
        // }
        //获取可用的麦克风设备
        const microphones = await NERTC.getMicrophones();
        const microphoneId = microphones?.microphoneId
        // if (!microphoneId) {
        //     logs.push("没有可以使用的麦克风");
        // }

        localStream = NERTC.createStream({
            uid: store.state.admin.t_admin_pk,                      // 本端的uid
            audio: true,                   // 是否从麦克风采集音频
            microphoneId: microphoneId,    // 麦克风设备 deviceId，通过 getMicrophones() 获取
            video: subscribeLocalVideo != null,   // 是否从摄像头采集视频
            cameraId: cameraId             // 摄像头设备 deviceId，通过 getCameras() 获取
        });

        //启动本地音视频流，销毁前无需重复初始化
        localStream.init().then(() => {
            logs.unshift('本地音频信息初始化完成。')

            // //用于播放视频的div元素
            if (subscribeLocalVideo) {
                //开始播放本地视频流
                localStream.play(subscribeLocalVideo)
                // 设置播放的视频容器大小  
                localStream.setLocalRenderMode({
                    width: subscribeLocalVideo.offsetWidth,
                    height: subscribeLocalVideo.offsetHeight,
                    cut: true    // 是否裁剪
                });
                logs.unshift("本地视频信息初始化完成。")
            }

            // 将本地音视频流发布至云信服务器，加入房间前不用执行此方法。
            client.publish(localStream).then(() => {
                logs.unshift('开始传输本地音（视）频信息。')
            },(err:any) => {
                logs.unshift("发布本地视频失败，可能没有加入频道");
                console.log(err);
            })
        })
    }

    /**
     * 初始化远端流
     */
    const initRemoteStream = async (subscribeRemoteVideo?: HTMLElement) => {
        // 侦听有远程流加入
        client.on('stream-added', (evt: any) => {
            const remoteStream = evt.stream;
            if (userListData.findIndex(v => v.remoteStream == remoteStream) != -1) {
                return;
            }
            //设置要订阅音频或者视频
            remoteStream.setSubscribeConfig({
                audio: true,//订阅麦克风音频
                audioSlave: true,//订阅音频辅流
                video: subscribeRemoteVideo != null,//订阅视频
                screenShare: false,//订阅屏幕共享
                highOrLow: NERTC.STREAM_TYPE.HIGH,//订阅大流
            })
            //发起订阅
            client.subscribe(remoteStream).then(() => {
                logs.unshift(`订阅对方的流成功`);
                console.log('发起订阅对端成功')
            })
        })

        // 订阅视频
        client.on('stream-subscribed', (evt: any) => {
            const userID = evt.stream.getId();
            console.log("userId = ",userID);
            // console.warn(`收到订阅 ${userId} 的 ${evt.mediaType} 成功的通知`) // mediaType为：'audio' | 'video' | 'screen'
            //这里可以根据mediaType的类型决定播放策略
            const remoteStream = evt.stream;
            const user = userListData.find(v => v.t_admin_pk == userID);
            console.log("user = ",user);
            if (user && !user.remoteStream) {
                user.remoteStream = remoteStream;
            }

            remoteStream.play(subscribeRemoteVideo).then(() => {
                // 订阅了视频
                if (subscribeRemoteVideo) {
                    remoteStream.setRemoteRenderMode({
                        width: subscribeRemoteVideo.offsetWidth,
                        height: subscribeRemoteVideo.offsetHeight,
                        cut: true
                    })
                    logs.unshift(`播放${userID}的音视频成功`)
                } else {
                    logs.unshift(`播放${userID}的音频成功`)
                }
            });
        })
    }

    /**
     * 添加侦听器
     */
    const addEventListener = () => {
        // 侦听有远端用户加入房间
        client.on('peer-online', (evt: any) => {
            const userID = evt.uid;
            if (userListData.findIndex(v => v.t_admin_pk == userID) == -1) {
                userListData.push({ t_admin_pk: userID });
                logs.unshift(`“${userID}”加入房间`);
            }
        })

        // 侦听有远端用户离开房间
        client.on('peer-leave', (evt: any) => {
            const userID = evt.uid;
            const index = userListData.findIndex(v => v.t_admin_pk == userID);
            if (index >= 0) {
                userListData.splice(index, 1);
                logs.unshift(`“${userID}”离开房间`);
            }
        })
    }

    /**
	 * 设置是否播放用户的音频信息
	 */
    const setRemoteAudio = ({ userID, bool }: { userID: number, bool: boolean }) => {
        const user = userListData.find(v => v.t_admin_pk == userID);
        if (!user) {
            return;
        }
        const remoteStream = user.remoteStream;
        if (!remoteStream) {
            console.log("请检测是否是测试数据，没有remoteStream。")
            return;
        }
        if (bool) {
            client.subscribe(remoteStream).then(() => {
                logs.unshift(`重新打开${user.t_admin_pk}的音频成功`);
                user.disableAudio = false;
            }, () => {
                logs.unshift(`重新打开${user.t_admin_pk}的音频失败`);
            })
        } else {
            client.unsubscribe(remoteStream, { audio: true }).then(() => {
                logs.unshift(`关闭${user.t_admin_pk}的音频成功`);
                user.disableAudio = true;
            }, () => {
                logs.unshift(`关闭${user.t_admin_pk}的音频失败`);
            })
        }
    }

    /**
     * 是否打开本地麦克风采集
     * @param bool 
     * @returns 
     */
    const setLocalAudio = async (bool: boolean) => {
        if (!localStream) {
            return;
        }
        // 关闭麦克风
        if (!bool) {
            try {
                await localStream.close({ type: "audio" });
                logs.unshift("关闭麦克风");
                localAudio.value = false;
            } catch (e) {
                logs.unshift("关闭麦克风失败（请检测是否有可用的麦克风）");
                console.log(e);
            }
            // 开启麦克风
        } else {
            try {
                await localStream.open({ type: "audio" });
                logs.unshift("开启麦克风");
                localAudio.value = true;
            } catch (e) {
                logs.unshift("开启麦克风失败（请检测是否有可用的麦克风）");
                console.log(e);
            }
        }
    }

    const setLocalVideo = async (bool: boolean) => {
        if (!localStream) {
            return;
        }
        // 关闭摄像头
        if (!bool) {
            try {
                await localStream.close({ type: "video" });
                logs.unshift("关闭摄像头");
                localVideo.value = false;
            } catch (e) {
                logs.unshift("关闭摄像头失败（请检测是否有可用的摄像头）");
                console.log(e);
            }
        } else {
            try {
                await localStream.open({ type: "video" });
                logs.unshift("开启摄像头");
                localVideo.value = true;
            } catch (e) {
                logs.unshift("开启摄像头失败（请检测是否有可用的摄像头）");
                console.log(e);
            }
        }
    }


    // const setRecordDeviceMute = () => {
    //     recordDeviceMute.value = !recordDeviceMute.value;
    //     if (muteLocalAudio.value) {
    //         localStream.close({ type: "video" });
    //     } else {
    //         localStream.open({ type: "video" });
    //     }
    //     client.setRecordDeviceMute(recordDeviceMute.value);
    // }

    return {
        localAudio,
        localVideo,
        joinChannel,
        setJoinChannel,
        setLocalAudio,
        setLocalVideo,
        setRemoteAudio,
        token,
        logs,
        userListData,
        initLocalStream,
        initRemoteStream
    }
}

export default setup;
